namespace Legend.IoCo
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// An implementation of the IContainer-interface that uses a dictionary
    /// to map services.
    /// </summary>
    public class IoCoDefaultContainer
        : IContainer
    {
        private Dictionary<Type, Func<IComponentResolver, object>> registrations;

        public IoCoDefaultContainer()
        {
            this.registrations = new Dictionary<Type, Func<IComponentResolver, object>>();
        }

        public void Register(IEnumerable<Type> supportedTypes, Func<IComponentResolver, object> creator)
        {
            AssertTypesCollectionIsNotNull(supportedTypes);
            AssertThatCreatorIsNotNull(creator);

            foreach (var type in supportedTypes)
            {
                this.registrations.Add(type, creator);
            }
        }
        
        public bool TryResolve(Type typeToResolve, out object result)
        {
            Func<IComponentResolver, object> creator = null;

            if (!this.registrations.TryGetValue(typeToResolve, out creator))
            {
                result = null;
                return false;
            }

            result = creator.Invoke(this);
            return true;
        }

        private static void AssertThatCreatorIsNotNull(Func<IComponentResolver, object> creator)
        {
            if (creator == null)
            {
                throw new ArgumentNullException("creator");
            }
        }

        private static void AssertTypesCollectionIsNotNull(IEnumerable<Type> supportedTypes)
        {
            if (supportedTypes == null)
            {
                throw new ArgumentNullException("supportedTypes");
            }
        }
    }
}